package com.cyf.common.core.io;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenyifan
 * @create 2024-11-25 14:27
 */
public class ClassPathResourceUtil {

    /**
     * 解决打成 jar包时读取不到 resoures 目录下的文件
     * resource下的文件是存在于jar这个文件里面，在磁盘上是没有真实路径的，所以通过ResourceUtils.getFile或者this.getClass().getResource("")方法无法正确获取文件。
     * 但是在jar包中可以拿到文件流。
     * @param path
     * @return
     */
    public static String getContent(String path) {
        ClassPathResource classPathResource = new ClassPathResource(path);
        try (InputStream is = classPathResource.getInputStream()) {
            return StreamUtils.copyToString(is, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取资源路径下的所有类
     * @param resourcesPath 资源路径
     * @return
     * @throws ClassNotFoundException
     * @throws IOException
     */
    public static List<Class<?>> getClasses(String resourcesPath) {
        // 如 classpath:com/github/cyf/entity/**/*.class，获取 entity 及其子包下的所有类
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            Resource[] resources = resolver.getResources(resourcesPath);
            SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
            List<Class<?>> classes = new ArrayList<>();
            for(Resource resource :resources) {
                // 先获取resource的元信息，然后获取class元信息，最后得到 class 全路径
                String clsName = metadataReaderFactory.getMetadataReader(resource).getClassMetadata().getClassName();
                classes.add(Class.forName(clsName));
            }
            return classes;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}